<template>
  <div class="employees-container">
    <div class="app-container">
      <!-- 通用工具栏组件使用 -->
      <page-tools>
        <!-- 自定义左侧内容 -->
        <template #slot-left>
          <span>共{{ total }}条记录</span>
        </template>

        <!-- 自定义右侧内容 -->
        <template #slot-right>
          <el-button v-power="'import'" type="danger" size="small" @click="$router.push('/excel')">导入excel</el-button>
          <el-button v-power="'export'" type="success" size="small" @click="deriveExcel">导出excel</el-button>
          <el-button type="primary" size="small" @click="addStaffFn">新增员工</el-button>
        </template>
      </page-tools>

      <el-card style="margin-top: 10px;">
        <el-table border :data="employeesList" :default-sort="{prop: 'timeOfEntry', order: 'descending'}">
          <el-table-column label="序号" type="index" />
          <el-table-column label="姓名" prop="username" />
          <el-table-column label="头像" prop="staffPhoto">
            <template v-slot="{ row }">
              <image-holder :src="row.staffPhoto" />
            </template>
          </el-table-column>
          <el-table-column label="手机号" prop="mobile" />
          <el-table-column label="工号" prop="workNumber" />
          <el-table-column label="聘用形式" prop="formOfEmployment" :formatter="formOfEmploymentFormatterFn">
            <!--
              判断的数据少可以用这种方法
              <template v-slot="scope">
              {{ scope.row.formOfEmployment*1 === 1 ? '正式': scope.row.formOfEmployment*1 === 2?'非正式':'未知' }}

            </template> -->
          </el-table-column>
          <el-table-column label="部门" prop="departmentName" />
          <el-table-column label="入职时间" prop="timeOfEntry" sortable :sort-method="timeOfEnteySortFn">
            <template v-slot="scope">
              {{ scope.row.timeOfEntry | formatTime }}
            </template>
          </el-table-column>
          <el-table-column label="操作" width="280">
            <template v-slot="scope">
              <el-button type="text" size="small" @click="lookDetailFn(scope.row.id)">查看</el-button>
              <el-button type="text" size="small" @click="assignRoleFn(scope.row.id)">分配角色</el-button>
              <el-button type="text" size="small" @click="deleteStaffFn(scope.row.id)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>

        <!-- 分页组件 -->
        <el-row type="flex" justify="center" align="middle" style="height: 60px">
          <!-- 分页区域 -->
          <el-pagination
            :current-page="query.page"
            :page-sizes="[10, 15, 20, 25]"
            :page-size="query.size"
            layout="total, sizes, prev, pager, next, jumper"
            :total="total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
        </el-row></el-card>
      <!-- 新增员工 弹窗 -->
      <el-dialog title="新增员工" :visible.sync="dialogVisible" @close="closeDialogFn">
        <emp-dialog
          ref="empDialog"
          :dialog-visible.sync="dialogVisible"
          :depar-tree-list="deparTreeList"
          @addEmpEV="addEmpFn"
        />
      </el-dialog>

      <!-- 分配角色 弹窗-->
      <el-dialog :visible.sync="roleShowDialog" title="分配角色">
        <assign-role ref="Role" v-model="roleShowDialog" :all-role-list="allRoleList" @saveRoleIdsEv="saveRoleIdsEv" />
      </el-dialog>
    </div>
  </div>
</template>

<script>
// 将固定的值单独封装 引入
import EmployeeEnum from '@/api/constant'
import { getEmployeesListAPI, deleteAtaffMessageAPI, addEmployeesAPI, getAllRoleListAPI, getUserDetailById, giveEmpAssignRoleAPI } from '@/api/employees'
import { getDepartmentsListAPI } from '@/api/departments'
// 将平铺的数组结构转成树形结构
import { tranListToTreeData } from '@/utils'
// 导入子组件(插槽)
// import PageTools from '@/components/PageTools'
// 全局注册组件
// 为什么可以在任何地方全局注册组件(注意必须全局注册的组件先展示)\
// main.js->webpack打包的'入口' 所有的代码都会'先执行'
// Vue.component()->这行代码才叫全局注册组件(组件标签全局挂在到VUe体系里)
// import Vue from 'vue'
// Vue.component('PageTools', PageTools)
import empDialog from './empDialog.vue'
import dayjs from 'dayjs'
import assignRole from './assignRole.vue'
export default {
  // 注册组件
  // components: {
  //   PageTools
  // }
  name: 'Employees',
  components: {
    empDialog,
    assignRole
  },
  filters: {
    formatTime(time) {
      return dayjs(time).format('YYYY-MM-DD')
    }
  },
  data() {
    return {

      query: {
        page: 1, // 页码
        size: 10 // 每页条数
      },
      employeesList: [], // 员工列表
      total: 0, // 数据总条数
      dialogVisible: false, // 控制弹框是否显示
      deparTreeList: [],
      roleShowDialog: false,
      allRoleList: [],
      clickEmpId: ''
    }
  },
  created() {
    // 调用获取员工列表
    this.getEmployeesListFn()
    // 获取部门列表
    this.getDepartmentsListFn()
    // 获取角色列表
    this.getRoleListFn()
  },
  methods: {
    // 获取员工列表
    async getEmployeesListFn() {
      const res = await getEmployeesListAPI(this.query)
      // console.log(res)
      if (!res.success) return
      this.employeesList = res.data.rows
      this.total = res.data.total
    },
    // 获取部门列表
    async getDepartmentsListFn() {
      const res = await getDepartmentsListAPI()
      // console.log(res)
      this.deparTreeList = tranListToTreeData(res.data.depts, '')
    },
    // 获取角色列表
    async getRoleListFn() {
      const res = await getAllRoleListAPI()
      // console.log(res)
      const res2 = await getAllRoleListAPI({
        page: 1,
        pagesize: res.data.total
      })
      // console.log(res2)
      this.allRoleList = res2.data.rows || []
    },
    // 每页显示的条数发生改变时触发
    handleSizeChange(newSize) {
      this.query.size = newSize
      this.getEmployeesListFn()
    },

    // 当前页面发生改变时触发
    handleCurrentChange(newPage) {
      this.query.page = newPage
      this.getEmployeesListFn()
      // 扩建知识:  我们直接把请求放在created里 以后this.created()不行吗 不行
      // 因为钩子函数(生命周期函数8个) 是没有挂载到组件身上 所以不能用this调用钩子函数
    },
    // 格式化-聘用形式内容
    formOfEmploymentFormatterFn(row) {
      // row 其实就是scope.row 行的数据对象
      const obj = EmployeeEnum.hireType.find(item => item.id === row.formOfEmployment * 1)
      // 找到了用value的值 找不到就返回'未知'字符串给列内容
      return obj ? obj.value : '未知'
    },
    // 入职时间-排序
    timeOfEnteySortFn(a, b) {
      if (!a.timeOfEntry) {
        a.timeOfEntry = '1970-01-01'
      }
      if (!b.timeOfEntry) {
        b.timeOfEntry = '1970-01-01'
      }
      const aDate = new Date(a.timeOfEntry)
      const bDate = new Date(b.timeOfEntry)
      return aDate.getTime() - bDate.getTime()
    },
    // 删除员工功能
    async deleteStaffFn(staffId) {
      const res = await deleteAtaffMessageAPI(staffId)
      if (this.employeesList.length === 1 && this.query.page !== 1) {
        this.query.page--
      }
      if (!res.success) return
      this.$message.success(res.message)
      this.getEmployeesListFn()
    },
    // 显示弹框
    addStaffFn() {
      this.dialogVisible = true
    },
    // 子传父数据接受
    async addEmpFn(addEmpEV) {
      addEmpEV.timeOfEntry = dayjs(addEmpEV.timeOfEntry).format('YYYY-MM-DD')
      await addEmployeesAPI(addEmpEV)
      this.getEmployeesListFn()
    },
    // 关闭弹框+表单
    closeDialogFn() {
      // 表单重置
      // this.$refs.empDialog  找到的是empDialog.vue组件对象 (类似empDialog.vue组件的this)
      this.$refs.empDialog.$refs.staffFrom.resetFields()
    },
    // 导出表格
    async deriveExcel() {
      // webpack提供的一个import函数
      // 引入一个文件, 原地得到一个Promise对象
      // Promise对象里成功的导入的结果 就是文件模块导出的东西

      // 业务:导出所有数据到表格文件里
      // 1.我们要拿到所有要导出的员工列表的数据->不能用上面的employeesList(它只有当前页面条数数据)
      const res = await getEmployeesListAPI({
        page: 1, // 页码
        size: this.total
      }) // 试试不传参可以获取所有员工列表吗? 不可以,因为后台默认传回10条数据
      // 2. 为何要自己写参数对象, 不用改this.query 因为this.query是铺设页面用的 而我此接口只为了拿到所有数据
      // console.log(res)
      const empList = res.data.rows
      // 根据后台返回的字段直接全部导出10对key+value(没有顺序)
      // 3.准备数据结构,为导出表格做准备(数据准备)
      // 重点:一定要知道现有东西,想要要的数据结构
      // 现有数组里套对象(英文key)
      // 想要二维数组 小数组里面是数据 表格一行数据(中文key)
      // 额外:准备表头数组
      // 3.0先准备列表头中文数组-映射好 英文对应中文转换值
      // 写代码
      // const myObj = {
      //   'id': '编号',
      //   'password': '密码',
      //   'mobile': '手机号',
      //   'username': '姓名',
      //   'timeOfEntry': '入职日期',
      //   'formOfEmployment': '聘用形式',
      //   'correctionTime': '转正日期',
      //   'workNumber': '工号',
      //   'departmentName': '部门',
      //   'staffPhoto': '头像地址'
      // }
      // // 3.1拿到英文key的字符串数组 (对象是无序的)
      // const headerKeys = Object.keys(empList[0])
      // // 3.2 遍历出每个英文key,换出每个中文key 形成数组
      // const tHeader = headerKeys.map(item => { // map会遍历左侧数组里每个值 传给enKey形参执行一次函数体
      //   return myObj[item] // 执行一次函数体 就return值给map内部 收集到一个新数组里(push进)
      // }) // 等待map循环enKeyArr结束 新的数组(里面中文key)返回到原地
      // // console.log(tHeader)
      // // 3.3拿到值得数组
      // const valueArr = empList.map(obj => {
      //   return Object.values(obj)
      // })
      // 考虑顺序(页面上列保持一致顺序)
      // 4.1 自己按页面顺序写一个表头数组 数组遍历是保持顺序的
      const tHeader = ['序号', '姓名', '头像', '手机号', '工号', '聘用形式', '部门', '入职时间']
      // 4.2 数据key映射关系 (思路:遍历上边数组按照顺序,取出中文的名字 但对应的数组值的数组  要从英文key里取出value值 我要用中文key换到英文key 再去取到值  )
      const myObj = {
        // 序号 直接用数组下标加1
        '手机号': 'mobile',
        '姓名': 'username',
        '入职时间': 'timeOfEntry',
        '聘用形式': 'formOfEmployment',
        '工号': 'workNumber',
        '部门': 'departmentName',
        '头像': 'staffPhoto'
      }
      const resultArr = empList.map((item, index) => {
        const valueArr = []
        tHeader.forEach(zhKey => {
          if (zhKey === '序号') {
            valueArr.push(index + 1)
          } else {
            const enKey = myObj[zhKey]
            valueArr.push(item[enKey])
          }
        })
        return valueArr
      })

      // console.log(resultArr)
      import('@/vendor/Export2Excel').then(excel => {
        // const tHeader = ['序号', '姓名', '爱好']
        // const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
        // const list = this.list
        // const data = this.formatJson(filterVal, list)
        // console.log(data)
        excel.export_json_to_excel({ // 才是关键->调用Export2Excel.js中导出方法
          header: tHeader, // 表头
          data: resultArr, // 每一行的数据 二维数组
          filename: '人资项目导出', // 文件名
          autoWidth: true, // 自动宽度
          bookType: 'xlsx' // xlsx文件类型
        })
      })
    },
    // 查看详情
    lookDetailFn(empId) {
      this.$router.push(`/employees/detail?id=${empId}`)
    },
    // 分配角色 -按钮事件
    async assignRoleFn(empId) {
      this.roleShowDialog = true
      this.clickEmpId = empId

      const res = await getUserDetailById(empId)
      console.log(res)
      // 为什么有两个角色 只显示一个
      // 因为数据不一致造成  之前人员身上是有两个角色  有人删掉了一个  后端没有做处理 所有出现了问题
      this.$refs.Role.roleIds = res.data.roleIds
    },
    // 给员工分配角色
    async saveRoleIdsEv(roleIdArr) {
      const res = await giveEmpAssignRoleAPI(this.clickEmpId, roleIdArr)
      // console.log(res)
      if (res.$success) return
      this.$message.success(res.message)
      this.roleShowDialog = false
    }
  }

}

</script>

<style lang="scss" scoped>

</style>
